<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
	</head>
	<body>
		<button>点击</button>

		<script>
			let that;
			let _that;
			class Star {
				constructor(uname, age) {
					// constructor 里面的 this 指向的是创建的实例对象
					that = this;
					console.log(this);

					this.uname = uname;
					this.age = age;
					// this.sing();
					this.btn = document.querySelector('button');
					this.btn.onclick = this.sing; // 不要加小括号，如果加了，就直接调用，不加就是点击后才调用
				}
				sing() {
					// 这个 sing 方法里面的 this 指向的是 btn 这个按钮，因为这个按钮调用了这个方法
					console.log(this);
					console.log(this.uname); // this 指向的是 btn，而 btn 没有 uname，所以打印 undefined
					console.log(that.uname); // that 存的是 constructor 里的 this，指向调用者 xs，所以可以打印出来
				}
				dance() {
					// 这个 dance 里面的 this 指向的是实例对象 xs，因为 xs 调用了这个函数
					_that = this;
					console.log(this);
				}
			}

			let xs = new Star('许嵩');
			xs.sing();
			console.log(that === xs);
			xs.dance();
			console.log(_that === xs);

			// 1. 在 ES6 中类没有变量提升，所以必须先定义类，才能通过类实例化对象
			// 2. 类里面的共有的属性和方法一定要加 this 使用
			// 3. 类里面 this 指向问题

			// this 指向问题
			// (1) constructor 里的 this 指向实例对象
			// (2) 方法的 this 指向此方法的调用者（向上面的 xs 或者 btn）
			// (3) 在某个方法里的 this 指向的不是 constructor 里的 this，但需要使用 constructor 里的 this，此时可以在外面声明一个全局变量（例如上面的 that），在 constructor 里面将 this 保存给这个全局变量，这样在任何地方都可以使用 constructor 里的 this 了
		</script>
	</body>
</html>
